package br.unicarioca.viaexpositus
import java.util.regex.Pattern
import java.util.regex.Matcher

class SiteController extends BaseAutenticacao {

	//ini Mapear site*****************
	def	linksPaginasPendentes = []
	def linkDominio
	def site
    int indexPag = 0

    def backgroundService
    def relatorioAsesService
	//ini Mapear site*****************
	
    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

    static defaultAction = "list"

    @AnotacaoDeAcao(nomeDaAcao="Listar", padrao="ROLE_ADMINISTRADOR,ROLE_ORGANIZACAO")
    def list = {
        params.max = Math.min(params.max ? params.int('max') : 10, 100)

        def siteInstanceList

        //Pegando a sessão do usuário
        Usuario usuarioLogado = getUsuario()
        if(usuarioLogado?.organizacao){
            siteInstanceList = Site.findAllByOrganizacao(usuarioLogado.organizacao)
        }else{
            siteInstanceList = Site.list()
        }

        [siteInstanceList: siteInstanceList, siteInstanceTotal: siteInstanceList.size()]
    }

    @AnotacaoDeAcao(nomeDaAcao="Salvar", padrao="ROLE_ADMINISTRADOR,ROLE_ORGANIZACAO")
    def save = {
        def siteInstance = new Site(params)

        Usuario usuario = getUsuario()
        println "session.usuario = "+usuario

        if(usuario){
            siteInstance.organizacao = usuario.organizacao
        }

        if (siteInstance.save(flush: true)) {
        	mapearSite(siteInstance)
            flash.message = "${message(code: 'default.created.message', args: [message(code: 'site.label', default: 'Site'), siteInstance.id])}"
            redirect(action: "list")
        } else {
            render(view: "edit", model: [siteInstance: siteInstance])
        }
    }

    @AnotacaoDeAcao(nomeDaAcao="Editar", padrao="ROLE_ADMINISTRADOR,ROLE_ORGANIZACAO")
    def edit = {

        if(params.id && params.id != "0"){
            def siteInstance = Site.get(params.id)
            if (siteInstance) {
                return [ siteInstance : siteInstance]
            }else{
                flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'site.label', default: 'Site'), params.id])}"
                redirect(action: "list")
            }
        } else {
            def siteInstance = new Site()
            return [siteInstance: siteInstance]
        }
    }

    @AnotacaoDeAcao(nomeDaAcao="Atualizar", padrao="ROLE_ADMINISTRADOR,ROLE_ORGANIZACAO")
    def update = {
        def siteInstance = Site.get(params.id)
        if (siteInstance) {
            if (params.version) {
                def version = params.version.toLong()
                if (siteInstance.version > version) {
                    
                    siteInstance.errors.rejectValue("version", "default.optimistic.locking.failure", [message(code: 'site.label', default: 'Site')] as Object[], "Another user has updated this Site while you were editing")
                    render(view: "edit", model: [siteInstance: siteInstance])
                    return
                }
            }
            siteInstance.properties = params
            if (!siteInstance.hasErrors() && siteInstance.save(flush: true)) {
                flash.message = "${message(code: 'default.updated.message', args: [message(code: 'site.label', default: 'Site'), siteInstance.id])}"
                redirect(action: "edit", id: siteInstance.id)
            }
            else {
                render(view: "edit", model: [siteInstance: siteInstance])
            }
        }
        else {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'site.label', default: 'Site'), params.id])}"
            redirect(action: "list")
        }
    }

    @AnotacaoDeAcao(nomeDaAcao="Remover", padrao="ROLE_ADMINISTRADOR,ROLE_ORGANIZACAO")
    def delete = {
        def siteInstance = Site.get(params.id)
        if (siteInstance) {
            try {
                siteInstance.delete(flush: true)
                flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'site.label', default: 'Site'), params.id])}"
                redirect(action: "list")
            }
            catch (org.springframework.dao.DataIntegrityViolationException e) {
                flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'site.label', default: 'Site'), params.id])}"
                redirect(action: "edit", id: params.id)
            }
        }
        else {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'site.label', default: 'Site'), params.id])}"
            redirect(action: "list")
        }
    }
    
    private void mapearSite(Site site){
		this.site = site
		linkDominio = site.url
        if(!linkDominio.contains("://")){
            linkDominio = "http://${linkDominio}"
        }
        linkDominio = linkDominio.replaceAll("(.*://.*/).*","\$1")
        log.info "linkDominio = ${linkDominio}"

		linksPaginasPendentes << site.url
        backgroundService.execute("mapeando -> ${site.url}", { buscarPaginas(site) })

    	
    }
    
    private buscarPaginas(def site){
    	try{
	    	log.info linksPaginasPendentes.size() +" - "+ indexPag
            def url
            while(linksPaginasPendentes.size() > indexPag){
                try{
                    url = linksPaginasPendentes[indexPag]
                    log.info "buscando -> ${url}"
                    def urlFormada = new URL(url)
                    URLConnection uc = urlFormada.openConnection()
                    uc.setConnectTimeout(30000)
                    def codigoFonte = urlFormada.getText()
                    buscarLinksDoMesmoDomínio(codigoFonte, urlFormada)
                    def pagina = Pagina.findByUrl(url)
                    if(!pagina){
                        pagina = new Pagina()
                        pagina.url = url
                        pagina.site = site
                    }

                    pagina.codigoFonte = codigoFonte
                    def avaliacao = relatorioAsesService.avaliarAcessibilidade(codigoFonte)
                    if(avaliacao){
                        if(!pagina.listaDeAvaliacoes){
                            pagina.listaDeAvaliacoes = []
                        }
                        pagina.addToListaDeAvaliacoes(avaliacao)
                    }
                    pagina.save(failOnError:true)
                }catch(SocketTimeoutException eTime){
                    //e.printStackTrace()
                    log.error "Timeout na url ${url}"
                }catch(Exception e){
                    e.printStackTrace()
                    log.error "Não foi possível salvar ${url}"
                }

                url = null
                indexPag++
            }
            log.info "Mapeamento finalizado."
    	}catch(Exception e){
    		e.printStackTrace()
    	}
    }
    
    private void buscarLinksDoMesmoDomínio(String codigoFonte, URL urlPai){
        Pattern patLink = Pattern.compile("href=\"([^<>\"]*?)\"")
        Matcher mat = patLink.matcher(codigoFonte)
        while(mat.find()){
            def link = mat.group(1)
            if(link){
                def url = new URL(urlPai,link)
                URLConnection uc = url.openConnection()
                uc.setConnectTimeout(30000)
                def type = uc.getContentType();
                def addr = url.toString()
                //log.info url
                if(type == "text/html"){
                    if(addr.endsWith("#")){
                        addr = addr.substring(0,addr.size()-1)
                    }
                    if((addr.startsWith(linkDominio) || addr.startsWith(linkDominio.replace("://", ":")) ) && !linksPaginasPendentes.contains(addr)){
                        linksPaginasPendentes << addr
                    }
                }
            }
        }
    }
}
